Amazon Location Service を使って GPS デバイスが特定エリアを出入りしたら通知する仕組みを作ってみた #reinvent
先日発表された新サービス「Amazon Location Service」 を使って、GPS デバイスの位置情報を活用する仕組みを作ってみました。
注意点
Amazon Location Service は、2020年12月17日現在でプレビューサービスです。そのため、本記事の内容は、今後サービスの仕様と異なる場合がありますのでご注意ください。
概要 - 秋葉原に出入りしたら通知する
今回は「秋葉原駅の周辺に出入りしたら通知」する仕組みを作ります。想定するシナリオは以下のようなものとします。
- GPS 機能のあるデバイスを想定(ソラコムの GPS マルチユニットなど)
- GPS デバイスの位置情報は MQTT で AWS IoT Core に Publish される
- 検知するエリアは「秋葉原駅周辺」
- 「秋葉原駅」周辺エリアに出入りしたタイミングで Amazon SNS 経由でメール通知する
構成図
全体の構成イメージは以下です。
やってみた
GeoJSON ファイルの作成
まず、特定エリアを定義する Json(GeoJSON)ファイルを用意します。geojson.io などの外部サービスで簡単に作成できます。
geojson.io のページ上で秋葉原駅周辺を適当に線で囲みます。地図右側のメニューから形を選択して囲んでみましょう。
エリアを選択できたら画面上のメニューより「Save」を選択して「GeoJSON」として保存します。このファイルは Amazon Location Service にアップロードして使うので、パソコンの適当な場所に保存しておきましょう。
Amazon Location Service の設定
次に、Amazon Location Service の設定です。今回は「Quick Start」から作成していきます。
そのまま「Get started」をクリックしてください。
ここではジオフェンスを追加しますので、先程ダウンロードしておいた GeoJSON ファイルをアップロードします。
アップロードできたら「Geofence collections」 を今回は明示的に指定して作成します。
適当な名前と説明を記入したら「Next」をクリックしてください。
次はトラッカーの設定です。先程と同様にトラッカーも明示的に指定して作成します。
先に設定したジオフェンスコレクションと、ここで指定するトラッカーがリンクされます。
名前と説明を入力して次に進みます。今回は「MyTracker1」としました。作成したトラッカーは、後ほど Lambda 関数で指定して使います。
このウィザードでは、EventBridge ルールと CloudWatch Logs が自動的に作成されます。後で動作確認時に使います。
レビュー画面で問題がなければ「Create resources」をクリックして作成します。
作成できたら下記画面のように、作成に成功した表示が見られます。後で使うので各リンクから EventBridge と CloudWatch Logs の画面を開いておくと楽です。
Lambda 関数の作成
次は Lambda 関数の作成です。今回は Python で作ります。
なお、Lambda に含まれる SDK はまだ最新ではないので、最新の SDK を含んだ形で作成します。作業の詳細は割愛しますが下記記事にある手順で最新の Boto3 を利用できるようにパッケージングしました。
関数はドキュメントにあるものをそのまま利用しています。コード中のコメントにあるようにTRACKER_NAME
変数には先程作成したトラッカー名に変更しておきましょう。
from datetime import datetime import json import os import boto3 # Update this to match the name of your Tracker resource TRACKER_NAME = "MyTracker1" """ This Lambda function receives a payload from AWS IoT Core and publishes device updates to Amazon Location Service via the BatchUpdateDevicePosition API. Parameter 'event' is the payload delivered from AWS IoT Core. In this sample, we assume that the payload has a single top-level key 'payload' and a nested key 'location' with keys 'lat' and 'long'. We also assume that the name of the device is nested in the payload as 'deviceid'. Finally, the timestamp of the payload is present as 'timestamp'. For example: >>> event { 'payload': { 'deviceid': 'thing123', 'timestamp': 1604940328, 'location': { 'lat': 49.2819, 'long': -123.1187 } } } If your data does not match this schema, you can either use the AWS IoT Core rules engine to format the data before delivering it to this Lambda function, or you can modify the code below to match it. """ def lambda_handler(event, context): # load the side-loaded Amazon Location Service model; needed during Public Preview os.environ["AWS_DATA_PATH"] = os.environ["LAMBDA_TASK_ROOT"] updates = [ { "DeviceId": event["payload"]["deviceid"], "SampleTime": datetime.fromtimestamp(event["payload"]["timestamp"]).isoformat(), "Position": [ event["payload"]["location"]["long"], event["payload"]["location"]["lat"] ] } ] client = boto3.client("location") response = client.batch_update_device_position(TrackerName=TRACKER_NAME, Updates=updates) return { "statusCode": 200, "body": json.dumps(response) }
Lambda 関数の作成が完了したら、このLambda が Amazon Location Service を利用できる権限を追加します。該当の関数にある IAMロールのリンクをクリックして IAMロール の画面を開きます。
下記のようなポリシーを追加します。今回はインラインポリシーとして追加しました。
ポリシーの内容はBatchUpdateDevicePosition
を許可するようにしています。必要に応じて対象トラッカーの指定など行ってください。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "WriteDevicePosition", "Effect": "Allow", "Action": "geo:BatchUpdateDevicePosition", "Resource": "arn:aws:geo:*:*:tracker/*" } ] }
AWS IoT ルールの作成
次は、パブリッシュされたメッセージを Lambda へ送る AWS IoT ルールを作成します。AWS IoT Core の画面から「Rules」をクリックします。IoT ルールの画面が開いたら右上の「Create」をクリックしてルールの作成を開始します。
ルールの内容は次のようにしました。
ルールのクエリは SELECT * FROM 'iot/location'
として、アクションには作成したLambda関数を指定します。
最後に、イベント発生を SNS へ通知するために EventBridge を設定しましょう。「Location Service」の設定で作成された EventBridge のルール画面を開きます。
デフォルトでは、SNS 通知のルールが無いので追加します。SNS トピックは必要に応じて事前に作成しておいてください。ルールのターゲットに追加できれば下記画面のようにCloudWach Logs と SNS の2つのターゲットが並びます。
CloudWatch Logs のターゲットは Location Service 設定時に自動的に追加されたものです。このロググループに記録されるのは、Lambda でBatchUpdateDevicePosition
API が呼び出されることによってジオフェンスに入るイベントです。このイベントをトリガーに EventBride 経由で SNS からメール通知される仕組みです。
動作テスト - 有楽町から秋葉原へ移動
以上で全て設定が完了したので、動作確認してみましょう!
今回は簡単にテストするために、AWS IoT Core のコンソールから位置情報をパブリッシュします。
画像のように、トピックには IoT ルールで指定したiot/location
を入力します。
パブリッシュするメッセージは下記です。最初に設定したジオフェンスの領域外にある有楽町からスタートする想定です。
準備ができたら「トピックに発行」をクリックして位置情報をパブリッシュします。
項目 | 説明 |
---|---|
timestamp | unixtime です。(2020-12-17 10:00:00) |
location | 有楽町駅前の座標です。 |
{ "payload": { "deviceid": "GPS-Device-001", "timestamp": 1608166800, "location": { "lat": 35.674439, "long": 139.764493 } } }
初回は何も発生しないので、次に秋葉原へ移動してジオフェンスの領域に入ってみましょう。パブリッシュするメッセージを次のように変更してパブリッシュします。
時間は前回より後の時間を指定します。仮に同じ時間を指定すると Location Service 側でエラーとなります。
項目 | 説明 |
---|---|
timestamp | unixtime です。(2020-12-17 10:20:00) |
location | 秋葉原にある書泉ブックタワー近くの座標です。 |
問題なければ、先程のCloudWatch Logs に Location Service のイベントログが記録されます。画像のように"EventType": "ENTER"
となっているので、ジオフェンス領域に入った(秋葉原周辺に入った)ことが分かります。
同じタイミングで SNS からメールも届いていました。
更に追加で、再度時間と場所を更新して有楽町駅前に戻ってみると "EventType": "EXIT"
というイベントが記録されてジオフェンス領域から出たことが分かります。
最後に
市販されている GPS トラッカーなどから AWS へ位置情報を送ることができれば、非常に簡単に位置情報アプリケーションが作成できそうな事が分かりました。
これまでは同じことをAWSサービスで実装する場合、下記記事のように設定がやや面倒な部分がありましたが、Amazon Location Service を使うと簡単に同様の仕組みが作れるようになりました。
他にも「キーワードマッチな周辺店舗の情報取得」などもできるようなので、活用用途はまだまだたくさんあると思います。Tokyoリージョンでも利用できますので、ぜひ活用してみてください!!